#include "SceneDefinations.h"

void TestScenes::CornellBox(Scene & scene) {
	scene.addPrimitive(make_shared<Sphere>(Vector3(-1e5 + 1, 40.8, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.75f, .25f, .25f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(1e5 + 99, 40.8, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.25f, .25f, .75f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 40.8, -1e5), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 40.8, 1e5 + 340), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(Colors::Black))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, -1e5, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 1e5 + 81.6, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f))));

	scene.addPrimitive(make_shared<Sphere>(Vector3(27, 16.5, 47), 16.5)->setMaterial(make_shared<ReflectiveMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f), 0.999f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(73, 16.5, 78), 16.5)->setMaterial(make_shared<RefractionMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f), 1.5, 0.999f)));
	//scene.addPrimitive(make_shared<Sphere>(Vector3(50, 681.6 - .27, 81.6), 600)->setMaterial(make_shared<LuminousMaterial>(make_shared<ColorMaterial>(Colors::White), 12.0f)));

	scene.addPrimitive(make_shared<Disk>(Vector3(50, 70, 81.6), Normal3(0, 1, 0), 30, true)
		->setMaterial(make_shared<LuminousMaterial>(make_shared<ColorMaterial>(Colors::White), 5.0f)));

	//scene.addLight(make_shared<PointLight>(Colors::White, Vector3(50, 50, 81.6), 1000.0f));

	shared_ptr<PerspectiveCamera> camera = make_shared<PerspectiveCamera>();
	camera->setEyePosition(Vector3(50, 52, 295.6), Normal3(0, -0.052612, -1));
	camera->setFov(30);
	scene.setCamera(camera);

	scene.setIntegrator(make_shared<PathIntegrator>(10, -1, 3, 6));
}

void TestScenes::CornellBox_LargeLight(Scene & scene) {
	scene.addPrimitive(make_shared<Sphere>(Vector3(-1e5 + 1, 40.8, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.0f, .6f, .0f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(1e5 + 99, 40.8, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.6f, .0f, .0f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 40.8, -1e5), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.95f, .95f, .95f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 40.8, 1e5 + 340), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(Colors::Black))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, -1e5, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.95f, .95f, .95f))));

	scene.addPrimitive(make_shared<Sphere>(Vector3(27, 16.5, 47), 16.5)->setMaterial(make_shared<ReflectiveMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f), 0.999f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(73, 16.5, 78), 16.5)->setMaterial(make_shared<RefractionMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f), 1.5, 0.999f)));
	scene.addPrimitive(make_shared<Disk>(Vector3(82, 46, 18), Normal3(0, 1, 0), 30)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.85f, .85f, .85f))));
	//scene.addPrimitive(make_shared<InfinatePlane>(Normal3(0, -1, 0), 90)->setMaterial(make_shared<LuminousMaterial>(make_shared<ColorMaterial>(Colors::White), 1.5f)));
	//scene.addPrimitive(make_shared<InfinatePlane>(Normal3(0, -1, 0), 90)->setMaterial(make_shared<LuminousMaterial>(make_shared<PerlinNoiseTexture>(0.1)->setMapping(Texture::Mapping::Position), 2.0f)));
	scene.addPrimitive(make_shared<InfinatePlane>(Normal3(0, -1, 0), 90)->setMaterial(make_shared<LuminousMaterial>(make_shared<CheckerTexture>(Vector3(0.06))->setMapping(Texture::Mapping::Position), 2.0f)));

	//scene.addLight(make_shared<PointLight>(Colors::White, Vector3(50, 81, 81.6), 2000.0f));

	/*shared_ptr<PerspectiveCamera> camera = make_shared<PerspectiveCamera>();
	camera->setEyePosition(Vector3(50, 52, 295.6), Normal3(0, -0.052612, -1));
	camera->setFov(30);*/

	shared_ptr<ThinLensCamera> camera = make_shared<ThinLensCamera>();
	camera->setEyePosition(Vector3(50, 52, 295.6), Normal3(0, -0.052612, -1));
	camera->setViewDistance(4.0);
	camera->setFocalDistance(248.6);
	camera->setLensRadius(0.2);
	scene.setCamera(camera);

	scene.setIntegrator(make_shared<PathIntegrator>(9, -1, 10, 6, 2));
}

void TestScenes::CornellBox_LargeLight_Mirror(Scene & scene) {
	scene.addPrimitive(make_shared<Sphere>(Vector3(-1e5 + 1, 40.8, 81.6), 1e5)->setMaterial(make_shared<ReflectiveMaterial>(.9f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(1e5 + 99, 40.8, 81.6), 1e5)->setMaterial(make_shared<ReflectiveMaterial>(.9f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 40.8, -1e5), 1e5)->setMaterial(make_shared<ReflectiveMaterial>(.9f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, 40.8, 1e5 + 340), 1e5)->setMaterial(make_shared<ReflectiveMaterial>(.9f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(50, -1e5, 81.6), 1e5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(.95f, .95f, .95f))));

	scene.addPrimitive(make_shared<Sphere>(Vector3(27, 16.5, 47), 16.5)->setMaterial(make_shared<ReflectiveMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f), 0.999f)));
	scene.addPrimitive(make_shared<Sphere>(Vector3(73, 16.5, 78), 16.5)->setMaterial(make_shared<RefractionMaterial>(make_shared<ColorMaterial>(.75f, .75f, .75f), 1.5, 0.999f)));
	
	//scene.addPrimitive(make_shared<Disk>(Vector3(50, 70, 81.6), Normal3(0, -1, 0), 20, false)->setMaterial(make_shared<LuminousMaterial>(make_shared<ColorMaterial>(Colors::White), 5.0f)));
	scene.addPrimitive(make_shared<InfinatePlane>(Normal3(0, -1, 0), 90)->setMaterial(make_shared<LuminousMaterial>(make_shared<CheckerTexture>(Vector3(0.06))->setMapping(Texture::Mapping::Position), 2.0f)));

	shared_ptr<ThinLensCamera> camera = make_shared<ThinLensCamera>();
	camera->setEyePosition(Vector3(50, 52, 295.6), Normal3(0, -0.052612, -1));
	camera->setViewDistance(4.0);
	camera->setFocalDistance(248.6);
	camera->setLensRadius(0.1);
	scene.setCamera(camera);

	scene.setIntegrator(make_shared<PathIntegrator>(200, -1, 2, -1, 2));
}

void TestScenes::Furnace(Scene & scene) {
	scene.addPrimitive(make_shared<Sphere>(Vector3(0, 5, 0), 5)->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(0.18f))));
	scene.setBackGround(make_shared<ColorMaterial>(1.0f));

	shared_ptr<PerspectiveCamera> camera = make_shared<PerspectiveCamera>();
	camera->setEyePosition(Vector3(0, 5, 15), Normal3(0, -0.1, -1));
	camera->setFov(70);
	scene.setCamera(camera);

	scene.setIntegrator(make_shared<PathIntegrator>(8, -1, 1, 3));
}

void TestScenes::Test(Scene & scene) {
	scene.addPrimitive(make_shared<InfinatePlane>(Normal3(0, 1, 0), 0, false)
		->setMaterial(make_shared<BlendMaterial>(
			make_shared<RoughReflectiveMaterial>(0.1),
			make_shared<DiffuseMaterial>(
				make_shared<CheckerTexture>(Vector3(0.3))->setMapping(Texture::Position)),
			BlendMaterial::BlendType::Add, 0.1f, 0.9f)
		)
	);
	scene.addPrimitive(make_shared<InfinatePlane>(Normal3(1, 0, 0), 12, false)
		->setMaterial(make_shared<BlendMaterial>(
			make_shared<ReflectiveMaterial>(),
			make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(0.4f, 0.2f, 0.7f)),
			BlendMaterial::BlendType::Add, 0.4f, 0.6f)
		)
	);

	scene.addPrimitive(make_shared<Sphere>(Vector3(5, 5, 0), 5)
		->setMaterial(make_shared<ReflectiveMaterial>(make_shared<ColorMaterial>(1.2f, 0.8f, 0.5f))));
	scene.addPrimitive(make_shared<Sphere>(Vector3(7, 3, 7), 4)
		->setMaterial(make_shared<DiffuseMaterial>(
			make_shared<ImageTexture>(
				make_shared<ByteImage>(string("C:\\Users\\dhb\\Pictures\\tex3.jpg"))
				)->setScale(1)
			))
	);
	scene.addPrimitive(make_shared<Sphere>(Vector3(-4.5, 4.5, 1), 4.5)
		->setMaterial(make_shared<FrostedRefractionMaterial>(
			make_shared<ColorMaterial>(0.5f, 0.9f, 0.6f), 1.5, 0.05, 1.0f, 1)
		)
	);
	scene.addPrimitive(make_shared<Sphere>(Vector3(-2, 5, -10), 5)
		->setMaterial(make_shared<DiffuseMaterial>(make_shared<ColorMaterial>(0.6f, 0.5f, 1.0f))));
	//scene.addPrimitive(make_shared<Disk>(Vector3(0.5, 3, 8), Normal3(0, 1, 0.2), 2)->setMaterial(make_shared<DiffuseMaterial>(make_shared<PerlinNoiseTexture>(Vector3(3))->setMapping(Texture::Mapping::Position))));
	//scene.addPrimitive((new Sphere(Vector3(0, 5, 15), 50))->setMaterial(new ReflectiveMaterial(new ColorMaterial(0.6f, 0.5f, 1.0f))));

	//scene.addLight(make_shared<FakeGIAmbientLight>(Color(0.2f, 0.18f, 0.07f), Color(0.05f)));
	//scene.addLight(make_shared<DirectionLight>(Colors::White, Vector3(-0.5, -0.5, -0.5), 0.7f));
	//scene.addLight(make_shared<PointLight>(Color(0.6f, 1f, 0.9f), Vector3(1, 7, 10), 20.0f));

	auto backGroundFunc = [](const Scene *scene, const Ray &ray, const IntersectResult &intersect) -> Color {
		const static Normal3 sunDir(1, 1, -2.2);
		const static Color sunColor = ColorByte(232, 93, 25) * 30.0f;
		const static Color skyColor = ColorByte(135, 206, 250);
		return skyColor + sunColor * fastExp((CLAMP(ray.dir * sunDir) - 1) * 150);
	};
	scene.setBackGround(make_shared<CustomMaterial>(backGroundFunc));
	/*scene.setBackGround(
	make_shared<LuminousMaterial>(
	make_shared<ImageTexture>(
	make_shared<RawImage>(string("C:\\Users\\dhb\\Pictures\\hdr2.hdr"))
	)->setMapping(Texture::Sky)->setOffset(Vector3(0, 0, 0))
	, 1.0f)
	);*/

	shared_ptr<ThinLensCamera> camera = make_shared<ThinLensCamera>();
	camera->setEyePosition(Vector3(0, 5, 18), Normal3(0, -0.1, -1));
	camera->setViewDistance(1.45);
	camera->setFocalDistance(17);
	camera->setLensRadius(0.1);
	scene.setCamera(camera);

	//scene.setIntegrator(make_shared<DirectIntegrator>(8));
	scene.setIntegrator(make_shared<PathIntegrator>(8, 2, 2, 3, 2));
}
